#pragma once

#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<functional>
#include"Connection.hpp"
#include"Log.hpp"
#include"InetAddr.hpp"

#define SIZE 1024


//普通的sockfd的封装
class Channel : public Connection
{
public:
    Channel(int sockfd,const InetAddr &client) : _sockfd(sockfd),_client_addr(client)
    {
        SetNonBlock(sockfd);
        //SetSockFd(sockfd);
    }
    void Recver() override
    {
        //LOG(LogLevel::DEBUG) << "事件到了channel模块";
        char buffer[SIZE];
        while(true)
        {
            buffer[0]=0;
            ssize_t n = recv(_sockfd,buffer,sizeof(buffer)-1,0);
            if(n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if(n == 0)
            {
                Excepter();
                return;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                }

            }
            //不为空的话，回调函数调到外部
            if(!_inbuffer.empty())
            {
                LOG(LogLevel::DEBUG) << "调用匿名函数";
                //_handler(std::shared_ptr<Connection>(this));//和protocol相关的匿名函数里面
                _outbuffer += _handler(_inbuffer);//和protocol相关的匿名函数里面
            }
            if(!_outbuffer.empty())
            {
                Sender();
                //除了上面的这种实现，当然也是可以直接去开启对写事件的关心，也就是下面的那个实现
                //GetOwner()->EnableReadWrite(_sockfd,true,true);
            }
        }
    }
    // //故意写成引用的形式
    // std::string& Inbuffer()
    // {
    //     return _inbuffer;
    // }
    // void Inbuffer(std::string* out)
    // {
    //     out = &_inbuffer;
    // }
    // void AppendOutBuffer(const std::string &out)
    // {
    //     _outbuffer += out;
    // }
    void Sender() override
    {
        while(true)
        {
            ssize_t n = send(_sockfd,_outbuffer.c_str(),sizeof(_outbuffer),0);
            if(n > 0)
            {
                _outbuffer.erase(0,n);
                if(_outbuffer.empty())
                    break;
            }
            else if(n == 0)
            {
                break;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)//我有5000块，一次要100，到第51次还会去要
                {
                    break;//缓冲区写满了
                }
                else if(errno == EINTR)
                {
                    //被信号中断了
                    continue;
                }
                else
                {
                    //真的出现异常了
                    Excepter();
                    return;
                }
            }
        }
        //1.要么是数据已经发送完了
        //2.要么是发送条件不具备
        if(!_outbuffer.empty())//发送之后可能没有发完
        {
            //开启对写事件的关心
            GetOwner()->EnableReadWrite(_sockfd,true,true);
        }
        else
        {
            GetOwner()->EnableReadWrite(_sockfd,true,false);
        }
    }
    void Excepter() override
    {
        //所有的错误都会在这里汇集
        GetOwner()->DeleteConnection(_sockfd);
    }
    int GetSockFd() override
    {
        return _sockfd;
    }
    ~Channel()
    {}
private:
    int _sockfd;
    std::string _inbuffer;//先用string，但是会有问题
    std::string _outbuffer;//先用string，但是会有问题

    //client info
    InetAddr _client_addr;

    // handler_t _handler;
};